# Copyright (C) 2002-2003, 2006 The Written Word, Inc.
# Copyright (C) 2000-2001 The Written Word, LLC
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# $Id: version.py 261 2006-09-21 17:20:13Z china $

import string
import re

# version number and revision class
class Version:
  def __init__ (self, ver):
    if not ver:
      self.ver = ['0']
    else:
      self.ver = str (ver).split ('.')

  def __nonzero__ (self):
    for ver in self.ver:
      if ver != '0':
        return True
    else:
      return False

  def __cmp__ (self, other):
    ver1 = []
    ver2 = []

    for x in self.ver:
      ver1.append (x)
    for x in other.ver:
      ver2.append (x)

    cmp = None
    while ver1:
      if ver2:
        ver1_num = ver1[0]
        ver2_num = ver2[0]

        del ver1[0]
        del ver2[0]

        # we compare first components of version. set to -1 if
        # less than, 0 if equal to, and 1 if greater than. as
        # more components are tested, if the result is the same,
        # continue, else stop because we have our result.

        # convert string to integer for numeric comparisons
        if re.match ('^\d+$', ver1_num) and re.match ('^\d+$', ver2_num):
          if int (ver1_num) < int (ver2_num):
            new_cmp = -1
          elif int (ver1_num) == int (ver2_num):
            new_cmp = 0
          else:
            new_cmp = 1
        else:
          if str (ver1_num) < str (ver2_num):
            new_cmp = -1
          elif str (ver1_num) == str (ver2_num):
            new_cmp = 0
          else:
            new_cmp = 1

        if not cmp:
          if new_cmp == 0:
            cmp = new_cmp
          else:
            return new_cmp
        else:
          if new_cmp != 0:
            return new_cmp

      else:
        return 1

    if not ver1 and ver2:
      return -1
    return 0

  def __str__ (self):
    return string.join (self.ver, '.')
  def __add__ (self, arg):
    return string.join (self.ver, '.') + arg
  def __radd__ (self, arg):
    return arg + string.join (self.ver, '.')

# test if program version or package release version meets
# dependency requirement
def met (tests, prog_ver, prog_rev):
  for test in tests:
    if not test:
      continue

    test_var = re.sub ('^(\w)([>=<]+)(.*)', '\\1', test)
    test_compare = re.sub ('^(\w)([>=<]+)(.*)', '\\2', test)
    test_ver = Version (re.sub ('^(\w)([>=<]+)(.*)', '\\3', test))

    if test_var == 'v':
      ver = prog_ver
    if test_var == 'r':
      ver = prog_rev

    if test_compare == '>' and ver <= test_ver:
      return False
    if test_compare == '>=':
      if ver < test_ver:
        return False
      if ver > test_ver:
        return True
    if test_compare == '==' and ver != test_ver:
      return False
    if test_compare == '<=' and ver > test_ver:
      return False
    if test_compare == '<' and ver >= test_ver:
      return False

  return True

# english-equivalent of test string
def english_test_string (tests):
  string = ''
  for test in tests.split ():
    test_var = re.sub ('^(\w)([>=<]+)(.*)', '\\1', test)
    test_compare = re.sub ('^(\w)([>=<]+)(.*)', '\\2', test)
    test_ver = re.sub ('^(\w)([>=<]+)(.*)', '\\3', test)

    if string:
      string += ', '

    if test_var == 'v':
      string += 'version'
    if test_var == 'r':
      string += 'revision'

    string += test_compare + test_ver

  return string
